package com.example.demo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.example.demo.dto.HttpContext;
import com.example.demo.dto.HttpInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.Map;

@RestController
@Slf4j
@RequestMapping("/rest")
public class RestTestController {

    private RestTemplate restTemplate = new RestTemplate();

    @PostMapping("test")
    public void restTest(@RequestBody HttpContext httpContext){
        HttpInfo httpInfo = httpContext.getHttpInfo();

        Map<String, ?> params = httpContext.getParams();
        String url = httpInfo.getUrl();

        HttpMethod method = findHttpMethod(httpInfo);
        ResponseEntity response;
        Class responseTypeClass = String.class;
        //HTTP通讯
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            String contentType = httpInfo.getContentType();
            if (!StringUtils.isEmpty(contentType)) {
                httpHeaders.setContentType(MediaType.valueOf(HttpResponseTypes.getMediaType(contentType)));
            }
            String id = null;
            RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
            long start = System.currentTimeMillis();
            if (HttpMethod.POST == method) {
                Object paramValues;
                //form表单类型
                if (HttpResponseTypes.FORM_CODE.equalsIgnoreCase(contentType)) {
                    //form形式发送原对象
                    MultiValueMap linkedMultiValueMap = new LinkedMultiValueMap();
                    for (String k : params.keySet()) {
                        String value = null;
                        Object o = params.get(k);
                        //form方式需发送成字符串
                        if (o != null) {
                            value = o.toString();
                        }
                        linkedMultiValueMap.add(k,value);
                    }
                    paramValues = linkedMultiValueMap;
                } else {
                    //json类型则发送字符串
                    paramValues = JSON.toJSONString(params, SerializerFeature.WriteMapNullValue);
                }
                log.info("三方API接口入参:{}",paramValues);
                HttpEntity<Object> requestEntity = new HttpEntity<>(paramValues, httpHeaders);
                response = restTemplate.postForEntity(url, requestEntity, responseTypeClass);
            } else if (HttpMethod.GET == method) {
                String newUrl = appendParamToUrl(url, params);
                if(params == null){
                    response = restTemplate.getForEntity(newUrl, responseTypeClass);
                }else{
                    response = restTemplate.getForEntity(newUrl, responseTypeClass, params);
                }

            } else {
                HttpEntity<String> requestEntity = new HttpEntity<>(httpHeaders);
                response = restTemplate.exchange(url, method, requestEntity, responseTypeClass, params);
            }

            long end = System.currentTimeMillis();
            log.info("responsemsg:{}", response.getBody());
        }catch (Exception e) {
            log.error("发送异常",e);
        }
    }

    private HttpMethod findHttpMethod(HttpInfo httpInfo) {
        String httpMethod = httpInfo.getHttpMethod();
        if (StringUtils.isEmpty(httpMethod)) {
            throw new RuntimeException("Method不能为空");
        }
        return HttpMethod.valueOf(httpMethod);
    }

    /**
     * 追加参数占位符到url后面
     *
     * @param url
     * @param params
     * @return
     */
    protected String appendParamToUrl(String url, Map<String, ?> params) {
        if (url.contains("?") || CollectionUtils.isEmpty(params)) {
            return url;
        } else {
            StringBuilder sb = new StringBuilder();
            sb.append(url).append("?");
            for (String name : params.keySet()) {
                sb.append(name).append("={").append(name).append("}&");
            }
            sb.delete(sb.length() - 1, sb.length());
            return sb.toString();
        }
    }
}
